package mianThread

import org.apache.poi.ss.usermodel.CellStyle
import org.apache.poi.ss.usermodel.CreationHelper

import org.apache.poi.xssf.streaming.SXSSFSheet
import org.apache.poi.xssf.streaming.SXSSFWorkbook
import xxdsqljob.JobCfg
import xxdsqljobDB.BeetlUtil
import xxdsqljobDB.ExcelUtil
import xxdsqljobDB.Job2ReportModel
import xxdsqljobDB.UpLoadFile
import xxdsqljobDB.XxdsqljobUtil

import java.util.concurrent.Executors
import java.util.concurrent.ScheduledExecutorService
import java.util.concurrent.ScheduledFuture
import java.util.concurrent.TimeUnit

/**
 * Created by Administrator on 2019-07-01.
 */
class XxsqlJobThread {
    public static ScheduledExecutorService executorService = Executors.newScheduledThreadPool(5);
    public static Map<String,ScheduledFuture> jobQue = new HashMap()
    public static final JOB_STATE_RUN = "RUN"
    public static final JOB_STATE_NORMAL = "NORMAL"
    public static final JOB_STATE_ERROR = "ERROR"
    public static final JOB_UNIT_SECONDS = "SECONDS"
    public static final JOB_UNIT_MINUTES = "MINUTES"
    public static final JOB_UNIT_HOURS = "HOURS"
    public static final JOB_UNIT_DAYS = "DAYS"


    static startDownLoad(long threadId){
        List<UpLoadFile> upLoadFile = new ArrayList()
        def errorMsg = "任务未配置Report"
        try {
            def reportList = XxdsqljobUtil.queryReport(threadId)
            if(!reportList){
                throw new Exception()
            }
            for (Job2ReportModel job2ReportModel:reportList){
                errorMsg = "${job2ReportModel.JOB_NAME}::${job2ReportModel.TITLE}"
                def fileName = job2ReportModel.getFileName()
                def physicalName =  job2ReportModel.getPhysicalFile( )
                //保存文件映射
                def file = ExcelUtil.createExcel2007(physicalName)
                def upLoadFile1 = XxdsqljobUtil.addFileMapping(fileName,physicalName)
                upLoadFile.add(upLoadFile1)
                SXSSFWorkbook workBook = ExcelUtil.getWorkbook()
                CellStyle headerStyle = ExcelUtil.createHeaderStyle(workBook)
                CellStyle bodyStyle = ExcelUtil.createBodyStyle(workBook)
                CreationHelper cellFormat = workBook.getCreationHelper();
                def sqlList = job2ReportModel.getSqlList()
                if(!sqlList){
                    errorMsg = "${job2ReportModel.JOB_NAME}::${job2ReportModel.TITLE}::${"未配置SQL"}"
                    throw new Exception()
                }
                for (String sqlId:sqlList){
                    SXSSFSheet sheet = ExcelUtil.getSheet(workBook,sqlId)
                    errorMsg = "${job2ReportModel.JOB_NAME}::${job2ReportModel.TITLE}::${sqlId}"
                    def sql = XxdsqljobUtil.getSql(sqlId)
                    def param = job2ReportModel.getParamMap()
                    sql = BeetlUtil.getStrTemplate(param,sql)
                    int total = XxdsqljobUtil.getTotal(sql)
                    int max = ExcelUtil.CACHE_SIZE
                    int page =  (total%max) ==0 ? (total/max):(total/max)+1
                    Map rowParam = [startIndex:0,
                                    headerStyle:headerStyle,
                                    bodyStyle:bodyStyle,
                                    cellFormat:cellFormat]
                    for(int offset=1;offset <= page ; offset ++){
                        errorMsg = "${job2ReportModel.JOB_NAME}::${job2ReportModel.TITLE}::${sqlId}::Query SQL or Write file error!"
                        def result =  XxdsqljobUtil.getPageData(sql,offset,max)
                        ExcelUtil.fillSheetData(sheet,result,rowParam)
                        result.clear()
                        System.gc()
                    }
                }
                ExcelUtil.writeFile(workBook,file)
            }
        }catch (Exception e){
            throw new Exception("${errorMsg}::${e.getMessage()?:""}")
        }
        return  upLoadFile
    }

    static doJob(long threadId,long initDate, long period, String unit){
        def flag = true
        try {
            println " jobName:${threadId}  initDate:${initDate}  period:${period}  unit:${unit}"
            def unitPeriod = getUnitMils(unit)
            if(!jobQue.keySet().contains(String.valueOf(threadId))){
                def startTime = cuteStartTimeLong(initDate,period,unit)
                def a =  executorService.scheduleAtFixedRate(new MyThread(threadId), startTime, Long.parseLong("${unitPeriod * period/1000}") , TimeUnit.SECONDS);
                jobQue.put(String.valueOf(threadId),a)
                println "Delay:${ startTime } Seconds; Period：${ (unitPeriod * period/1000)} Seconds"
                println("${new Date().format("yyyy-MM-dd HH:mm:ss")} job:${threadId} 已经添加!")
            }
        }catch ( Exception e){
            flag = false
            println "Job ${threadId} 启动失败...."
            e.printStackTrace()
        }
        return flag
    }

    static doJob(JobCfg jobCfg){
        //获取最近一次执行时间、如果无则取首次执行时间
        def initDate = jobCfg.getInitTime().getTime()
        return doJob(jobCfg.id,initDate,jobCfg.period,jobCfg.unit)
    }

    static closeJob(JobCfg jobCfg){
        return closeJob(jobCfg.id)
    }

    static closeJob(long threadId){
        def flag = false
        try{
            if(jobQue.keySet().contains(String.valueOf(threadId))){
                def a = jobQue.get(String.valueOf(threadId))
                if(a){
                    a.cancel(true)
                    if(a.isCancelled()){
                        jobQue.remove(String.valueOf(threadId))
                        flag = true
                        XxdsqljobUtil.updateJobCfgERROR(threadId,"人工干预JOB已停止...")
                        println("JOB:${threadId} 人工干预JOB已停止...")
                        a = null
                        XxdsqljobUtil.insertJobHis(threadId)
                    }else{
                        println "取消失败....."
                    }
                }else{
                    flag = true
                }

            }else{
                XxdsqljobUtil.updateJobCfgERROR(threadId,"人工干预JOB停止，实际该JOB未运行...")
                XxdsqljobUtil.insertJobHis(threadId)
                println "无JOB运行....."
                flag = true
            }
        }catch (Exception e){
            println "取消Job｛${threadId}｝:失败！：${e.getMessage()}"
            e.printStackTrace()
        }
        return  flag
    }

    /**
     * 重启服务器，计算下次执行时间
     * @param initDate
     * @param period
     * @param unit
     * @return
     */
    static  cuteStartTimeLong(long initDateMils,period,unit){
        print "正在计算延时时间......"
        long unitMils =  getUnitMils(unit) * period
        long current  = System.currentTimeMillis()
        while (initDateMils < current){
            initDateMils = initDateMils + unitMils
            current  = System.currentTimeMillis()
        }
        def delyMils = Math.round((initDateMils-current)/ getUnitMils(this.JOB_UNIT_SECONDS))
        return   delyMils
    }

    /**
     * 获取TimeUnit对象
     * @param unit
     * @return
     */
    static getUNIT(unit){
        def UNIT = TimeUnit.SECONDS
        switch (unit){
            case "SECONDS":
                UNIT = TimeUnit.SECONDS
                break;
            case "MINUTES":
                UNIT = TimeUnit.MINUTES
                break;
            case "HOURS":
                UNIT = TimeUnit.HOURS
                break;
            case "DAYS":
                UNIT = TimeUnit.DAYS
                break;
        }
        return UNIT
    }

    /**
     * 获取单位换算-毫秒
     * @param unit
     * @return
     */
    static getUnitMils(unit){
        long UNIT = 0
        switch (unit){
            case "SECONDS":
                UNIT = 1000
                break;
            case "MINUTES":
                UNIT = 1000*60
                break;
            case "HOURS":
                UNIT = 1000*60*60
                break;
            case "DAYS":
                UNIT = 1000*60*60*24
                break;
        }
        return UNIT
    }


}
